# Initial process execs /init.

#include "syscallno.h"
#include "initcode.h"

.globl start

# exec(init, argv)
start:

#     # a naïve loop test
#     mov x4, #0
#     mov x1, #65535
#     mov x2, #500
#     mul x3, x1, x2
# head:
#     cmp x4, x3
#     bne aha
#     mov x4, #0
#     mov x8, #SYS_hello
#     svc #0
# aha:
#     add x4, x4, #1
#     b head

    mov     x8, #SYS_fork
    svc     0x00
    cmp     x0, 0
    bgt     idle
    bne     exit     /* invalid fork return value */

    # for init process 1
    mov     x4, #N_COWORKER

cfork:
    cmp     x4, 0
    ble     skip
    sub     x4, x4, 1
    mov     x8, #SYS_fork
    svc     0x00
    cmp     x0, 0
    bgt     cfork
    bne     exit    /* invalid fork return value */

    # for coworkers
    mov     x8, #SYS_cop
    svc     0x00
    mov     x8, #SYS_exit
    svc     0x00
    b       exit

skip:
    mov     x8, #SYS_mogic
    svc     0x00

    # exec
    ldr     x0, =init
    ldr     x1, =argv
    mov     x8, #SYS_execve
    svc     0x00

exit:
    mov     x8, #SYS_exit
    svc     0x00
    b       exit

idle:
    # idle process should running on CPU0 to receive interrupts.
    mov     x8, #SYS_setaff
    mov     x1, 1
    svc     0x00

#    mov     x8, #SYS_exit
#    svc     0x00
loop:
    b       loop

# char init[] = "/init\0";
init:
    .string "/init\0"

# char *argv[] = { init, 0 };
.p2align 4
argv:
    .word init
    .word 0
    .word 0
    .word 0
